package lk.icta.common.web;

import lk.icta.common.AppConstants;
import lk.icta.common.service.DocumentManagementService;
import lk.icta.common.util.KmlWriter;
import lk.icta.core.dao.*;
import lk.icta.core.dto.*;
import lk.icta.core.entity.*;
import lk.icta.core.service.KachcheryManagementService;
import lk.icta.core.service.LandApplicationManagementService;
import lk.icta.core.service.LandManagementService;
import lk.icta.user.entity.User;
import org.codehaus.jackson.map.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;

/**
 * @author Duminda Dharmakeerthi
 */
public class JSONLandLookupService extends HttpServlet {

    private static final Logger logger = LoggerFactory.getLogger(JSONLandLookupService.class);
    private LandDAO landDAO;
    private AlienationDAO alienationDAO;
    private KachcheryManagementService kachcheryManagementService;
    private LandManagementService landManagementService;
    private LandAssociationDao landAssociationDao;
    private DocumentManagementService documentManagementService;
    private LandApplicationManagementService landApplicationManagementService;
    private final ObjectMapper mapper = new ObjectMapper();

    private LandRailwayDAO landRailwayDAO;
    private AlienationRailwayDAO alienationRailwayDAO;
    private PaymentDAO paymentDAO;

    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        WebApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext());

        landDAO = (LandDAO) context.getBean("landDAO");
        alienationDAO = (AlienationDAO) context.getBean("alienationDAO");
        landManagementService = (LandManagementService) context.getBean("landManagementService");
        landAssociationDao = (LandAssociationDao) context.getBean("landAssociationDao");
        documentManagementService = (DocumentManagementService) context.getBean("documentManagementService");
        landApplicationManagementService = (LandApplicationManagementService) context.getBean("landApplicationManagementService");
        kachcheryManagementService = (KachcheryManagementService) context.getBean("kachcheryManagementService");
        landRailwayDAO = (LandRailwayDAO) context.getBean("landRailwayDAO");
        alienationRailwayDAO = (AlienationRailwayDAO) context.getBean("alienationRailwayDAO");
        paymentDAO = (PaymentDAO) context.getBean("paymentDAO");

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String id = request.getParameter(WebConstants.ID);
        String mode = request.getParameter(WebConstants.MODE);
        String type = request.getParameter(WebConstants.TYPE);
        String modTypeId = request.getParameter("modTypeId");

        HashMap<String, Object> optionLists;
        try {
            logger.debug("Land lookup");
            HttpSession session = request.getSession();
            User user = (User) session.getAttribute(AppConstants.SESSION_USER_BEAN);
            Locale locale = (Locale) session.getAttribute(WebConstants.SESSION_USER_LANG);
            String language = locale.getLanguage();

            optionLists = new HashMap<String, Object>();
            List<Land> landList = new ArrayList<Land>();
            List<LandRailwayDetails> landRailwayDetailList = new ArrayList<LandRailwayDetails>();
            List<LandDetails> landDetailsList = new ArrayList<LandDetails>();
            List<LandApplicationDetail> landApplicationDetails = new ArrayList<LandApplicationDetail>();
            List<Kachchery> kachcheryList = new ArrayList<Kachchery>();
            List<LandAssociation> landAssociationList = new ArrayList<LandAssociation>();
            List<LandAssociationDetails> landAssociationDetailsList = new ArrayList<LandAssociationDetails>();
            if (type.equals("approval")) {
                if (mode.equals("byGNDivision")) {
                    if (Integer.parseInt(id) == AppConstants.ALL) {
                        // optionLists.put("landList", landDAO.getAllActivePendingLands(user));
                        //todo: move to service, remove lazy error
                        optionLists.put("landList", landManagementService.getActivePendingLandsByDSDivision(user));
                        logger.debug("Listing all pending lands for approval by {}", user.getUsername());
                    } else {
                        optionLists.put("landList", landManagementService.getActivePendingLandsByGNDivision(Integer.parseInt(id), user));
                        //TODO: Wrong log info - it doesn't print Number of lands.
                        logger.debug("Land Lookup by G.N. Division [No of lands: {}]", optionLists.size());
                    }
                } else if ("byDsDivision".equals(mode)) {
                    //orip user can get all lands of given DSid
                    optionLists.put("landList", landManagementService.getActivePendingLandsByDSDivisionId(Integer.parseInt(id), user));
                }
            } else if (type.equals("reject")) {
                if (mode.equals("byGNDivision")) {
                    if (Integer.parseInt(id) == AppConstants.ALL) {
                        // optionLists.put("landList", landDAO.getAllActivePendingLands(user));
                        //todo: move to service, remove lazy error
                        optionLists.put("landList", landManagementService.getRejectedLandsByDSDivision(user));
                        logger.debug("Listing all reject lands for approval by {}", user.getUsername());
                    } else {
                        optionLists.put("landList", landManagementService.getRejectedLandsByGNDivision(Integer.parseInt(id), user));
                        //TODO: Wrong log info - it doesn't print Number of lands.
                        logger.debug("Land Lookup by G.N. Division [No of lands: {}]", optionLists.size());
                    }
                }


            } else if (type.equals("init")) {
                if (mode.equals("byDistrict")) {
                    optionLists.put("landList", landDAO.getActiveLandsByDistrict(Integer.parseInt(id), user));
                    logger.debug("Land lookup by District [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("byDSDivision")) {
                    optionLists.put("landList", landDAO.getActiveLandsByDSDivision(Integer.parseInt(id), user));
                    logger.debug("Land lookup by D.S. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("byGNDivision")) {
                    if (Integer.parseInt(id) == 0) {
                        int dsDivisionId = user.getDsDivisions().iterator().next().getId();
                        optionLists.put("landList", landManagementService.getInitialActiveLandsByDSDivision(dsDivisionId, user));
                        logger.debug("Load initial lands of D.S. Division {} by {}", dsDivisionId, user.getUsername());
                    } else {
                        optionLists.put("landList", landManagementService.getInitialActiveLandsByGNDivision(Integer.parseInt(id), user));
                        logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());

                    }
                }
            } else if (type.equals("detail")) {
                if (mode.equals("byDistrict")) {
                    optionLists.put("landList", landDAO.getActiveLandsByDistrict(Integer.parseInt(id), user));
                    logger.debug("Land lookup by District [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("byDSDivision")) {
                    optionLists.put("landList", landDAO.getActiveLandsByDSDivision(Integer.parseInt(id), user));
                    logger.debug("Land lookup by D.S. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("byGNDivisionReport")) {
                    optionLists.put("landList", landManagementService.getDetailActiveLandDetailsByGNDivision(Integer.parseInt(id), user));
                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("byGNDivision")) {
                    if (Integer.parseInt(id) == AppConstants.ALL) {
                        landDetailsList = landManagementService.getAllIncompleteDetailLands(user);
                        landDetailsList.addAll(landManagementService.getAllActivePendingLands(user));
                    } else {
                        landDetailsList = landManagementService.getIncompleteDetailLandsByGNDivision(Integer.parseInt(id), user);
                        landDetailsList.addAll(landManagementService.getActivePendingLandsByGNDivision(Integer.parseInt(id), user));
                    }
                    optionLists.put("landList", landDetailsList);
                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());

                } else if (mode.equals("byGNDivisionLimit")) {

                    String pageNo = request.getParameter("pageNo");

                    if (Integer.parseInt(id) == AppConstants.ALL) {
                        landDetailsList = landManagementService.getAllActivePendingIncompleteLands(user, Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE);
                        //landDetailsList.addAll(landManagementService.getAllActivePendingLands(user));
                    } else {
                        landDetailsList = landManagementService.getAllActivePendingIncompleteLandsByGNDivision(user, Integer.parseInt(id), Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE);
                        //landDetailsList.addAll(landManagementService.getActivePendingLandsByGNDivision(Integer.parseInt(id), user));
                    }

                    optionLists.put("landList", landDetailsList);
                    logger.debug("Land lookup G.N. Division Limit [Number of lands: {}]", optionLists.size());

                } else if (mode.equals("approved")) {  //land association approved
                    logger.debug("land association approved");
                    optionLists.put("landList", landManagementService.getApprovedLandsByGNDivision(Integer.parseInt(id), user));
                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("associationView")) {  //land association view
                    logger.debug("land association view");
                    optionLists.put("landList", landManagementService.getLandAssociations(Integer.parseInt(id), user));
                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("associationApprove")) { //land association approve
                    logger.debug("land association to be approved");
                    optionLists.put("landList", landManagementService.getLandAssociationsToBeApproved(Integer.parseInt(id), user));
                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("defineAMAssociationApprove")) { //land association approve
                    logger.debug("land association to be approved");
                    optionLists.put("landList", landManagementService.getLandDefineAMAssociationsToBeApproved(Integer.parseInt(id), user));
                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("toBeDefineAMLandList")) {
                    logger.debug("land association toBeDefineAMLandList");
                    optionLists.put("landList", landManagementService.getLandToBeDefineAMAssociations(Integer.parseInt(id), user));
                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("toBeAssociationLandList")) {
                    logger.debug("land association toBeAssociationLandList");
                    optionLists.put("landAssociationDetailsList", landManagementService.getLandToBeAssociations(Integer.parseInt(id), user));
                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("byGNDivisionDetailReport")) {
                    optionLists.put("landList", landManagementService.getDetailLandReportByGNDivision(Integer.parseInt(id), user));

                    logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                } else if (mode.equals("byDSDivisionLimit")) {
                    String pageNo = request.getParameter("pageNo");
                    landDetailsList = landManagementService.getAllActivePendingIncompleteLandsByDsDivision(user, Integer.parseInt(id), Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE);
                    optionLists.put("landList", landDetailsList);
                } else if (mode.equals("byUserRail")) {
                    logger.debug("byUserRail");
                    String pageNo = request.getParameter("pageNo");

                    if (user.getRole().getId().equals(AppConstants.SC_USER_ROLE)) {
                        //optionLists.put("landRailwayDetailList", populateLandRailwayDetails(landRailwayDAO.getLandsByDistrictAndState(Integer.parseInt(id), LandRailway.State.DATA_ENTRY,user)));

                        EnumSet<AlienationRailway.State> stateSet = EnumSet.of(AlienationRailway.State.DATA_ENTRY,
                                AlienationRailway.State.REJECTED_BY_BO);


                       // optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByAlienation(alienationRailwayDAO.getAlienationRailwayByStateSet(user, stateSet, Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE)));
                    } else if (user.getRole().getId().equals(AppConstants.BO_USER_ROLE)) {
                        //optionLists.put("landRailwayDetailList", populateLandRailwayDetails(landRailwayDAO.getLandsByDistrictAndState(Integer.parseInt(id), LandRailway.State.PENDING,user)));

                        EnumSet<AlienationRailway.State> stateSet = EnumSet.of(AlienationRailway.State.DATA_ENTRY,
                                AlienationRailway.State.REJECTED_BY_SH);

                       // optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByAlienation(alienationRailwayDAO.getAlienationRailwayByStateSet(user, stateSet, Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE)));

                    } else if (user.getRole().getId().equals(AppConstants.SH_USER_ROLE)) {
                        //optionLists.put("landRailwayDetailList", populateLandRailwayDetails(landRailwayDAO.getLandsByDistrictAndState(Integer.parseInt(id), LandRailway.State.PENDING,user)));

                        EnumSet<AlienationRailway.State> stateSet = EnumSet.of(AlienationRailway.State.APPROVED_BY_BO,
                                AlienationRailway.State.REJECTED_BY_SDH);

                       // optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByAlienation(alienationRailwayDAO.getAlienationRailwayByStateSet(user, stateSet, Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE)));
                    } else if (user.getRole().getId().equals(AppConstants.SDH_USER_ROLE)) {
                        //optionLists.put("landRailwayDetailList", populateLandRailwayDetails(landRailwayDAO.getLandsByDistrictAndState(Integer.parseInt(id), LandRailway.State.PENDING,user)));

                        EnumSet<AlienationRailway.State> stateSet = EnumSet.of(AlienationRailway.State.APPROVED_BY_SH,
                                AlienationRailway.State.REJECTED_BY_DH);

                        //optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByAlienation(alienationRailwayDAO.getAlienationRailwayByStateSet(user, stateSet, Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE)));
                    } else if (user.getRole().getId().equals(AppConstants.DH_USER_ROLE)) {
                        //optionLists.put("landRailwayDetailList", populateLandRailwayDetails(landRailwayDAO.getLandsByDistrictAndState(Integer.parseInt(id), LandRailway.State.PENDING,user)));

                        EnumSet<AlienationRailway.State> stateSet = EnumSet.of(AlienationRailway.State.APPROVED_BY_SDH);

                        //optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByAlienation(alienationRailwayDAO.getAlienationRailwayByStateSet(user, stateSet, Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE)));
                    }


                    logger.debug("Land lookup by byUserRail [Number of lands: {}]", optionLists.size());


                } else if (mode.equals("byUserRailApproved")) {
                    logger.debug("byUserRailApproved");
                    String pageNo = request.getParameter("pageNo");
                    EnumSet<AlienationRailway.State> stateSet = EnumSet.of(AlienationRailway.State.APPROVED_BY_DH);
                    //optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByAlienation(alienationRailwayDAO.getAlienationRailwayByStateSet(user, stateSet, Integer.parseInt(pageNo), AppConstants.MAX_ROWS_PER_PAGE)));

                }
            } else if (type.equals("unAlienatedLands")) {
                if (mode.equals("byGNDivision")) {
                    if (Integer.parseInt(id) == 0) {
                        optionLists.put("landList", landManagementService.getAllApprovedUnAlienatedLands(user));
                        //  for (Land l : landManagementService.getAllApprovedUnAlienatedLands()) {
                        //  logger.debug("\n\n----- {} \n\n", l.getReferenceNumber());
                        //  }
                        //logger.debug("Listing all unalienated lands. [{}]", optionLists.size());
                    } else {
                        optionLists.put("landList", landManagementService.getApprovedUnAlienatedLandsByGNDivision(Integer.parseInt(id), user));
                        //logger.debug("Land lookup G.N. Division [Number of lands: {}]", optionLists.size());
                    }
                } else if (mode.equals("byGNDivisionUpperLevel")) {
                    if (Integer.parseInt(id) != 0) {
                        optionLists.put("landList", landManagementService.getApprovedUnAlienatedLandsByGNDivision(Integer.parseInt(id), user));

                    }
                }
            } else if (type.equals("initList")) {
                if (mode.equals("byGNDivision")) {
                    //  List<LandDetails> landDetailsList = new ArrayList<LandDetails>();
                    List<Land> lands = landManagementService.getDetailActiveLandsByGNDivision(Integer.parseInt(id), user);
                    for (Land land : lands) {
                        logger.debug("\nLand: {} ", land.getId());
                        LandDetails landDetails = new LandDetails();
                        landDetails.setId(land.getId());
                        landDetails.setNameOfLand(land.getNameOfTheLand());
                        landDetails.setPlanNumber(land.getPlanNumber());
                        landDetails.setLotNumber(land.getLotNumber());
                        if (alienationDAO.getActiveAlienationByLandId(land.getId(), user) != null) {
                            AlienationMethod alienationMethod = alienationDAO.getActiveAlienationByLandId(land.getId(), user).getAlienationMethod();
                            if (AppConstants.ENGLISH.equals(language)) {
                                landDetails.setAlienationMethod(alienationMethod.getEnName());
                            } else if (AppConstants.SINHALA.equals(language)) {
                                landDetails.setAlienationMethod(alienationMethod.getSiName());
                            } else if (AppConstants.TAMIL.equals(language)) {
                                landDetails.setAlienationMethod(alienationMethod.getTaName());
                            }
                        } else {
                            landDetails.setAlienationMethod(" - ");
                        }

                        landDetailsList.add(landDetails);
                    }
                    optionLists.put("landList", landDetailsList);
                }
            } else if (type.equals("kml")) {
                File ff = new File(AppConstants.CONTENT_ROOT + Integer.parseInt(modTypeId) + "/" + Integer.parseInt(mode) + "/" + Integer.parseInt(id) + ".kml");

                KmlWriter kmlWriter = new KmlWriter();
                String cordinate = kmlWriter.getCoordinateValueFromSavedFile(ff);
                List<Double> latlonList = kmlWriter.getOnlyLatLonValueFromSavedFile(cordinate);

                logger.debug("get Area from kml", latlonList);

                optionLists.put("getArea", latlonList);


            } else if (type.equals("kmlString")) {

                //get the Land
                Land land = landManagementService.getLandById(Long.parseLong(id));
                List<Double> latlonList = null;
                if (land != null) {
                    KmlWriter kmlWriter = new KmlWriter();
                    String kmlString = land.getKmlString();

                    if (kmlString != null) {
                        latlonList = kmlWriter.getOnlyLatLonValueFromSavedFile(kmlString);
                    }

                }
                logger.debug("get LatLanVal {}", latlonList);
                optionLists.put("latLanVal", latlonList);


            } else if (type.equals("mapData")) {

                //get the Land

                if ("".equals(id)) {
                    return;
                }
                logger.debug("mapDate - land id {}", id);
                Land land = landManagementService.getLandById(Long.parseLong(id));
                String code = null;
                String middle = null;
                String ref = null;
                if (land != null) {
                    String coordinate = land.getKmlString();
                    if (coordinate != null) {
                        code = coordinate;
                    }
                    String middlePoint = land.getKmlMiddlePoint();
                    if (middlePoint != null) {
                        middle = middlePoint;
                    }


                }
                logger.debug("get Map DAta", code);
                optionLists.put("coordinate", code);
                optionLists.put("middlePoint", middle);
                optionLists.put("kmlReferenceNumber", ref);

            } else if (type.equals("kmlLatLon")) {

                //get the kmlString
                String kmlString = request.getParameter("kmlStr");

                String latlon = null;
                if (kmlString != null) {
                    KmlWriter kmlWriter = new KmlWriter();
                    latlon = kmlWriter.getOnlyLatLonValue(kmlString);

                }
                logger.debug("get LatLanVal {}", latlon);
                optionLists.put("latLanVal", latlon);


            } else if (type.equals("searchApprovedLandsbyDS")) {
                int dsId = Integer.parseInt(id);
                if (dsId != 0) {
                    landList = landManagementService.searchAllActiveApprovedLandsOfDSDivision(dsId);
                }

                logger.debug("searchApproveLandsbyDS");
                optionLists.put("landList", landList);


            } else if (type.equals("searchByName")) {
                int dsId = Integer.parseInt(id);
                String searchText = request.getParameter("searchText");
                if (dsId != 0) {
                    landList = landManagementService.searchActiveLandsOfDSDivisionByLandName(searchText, dsId, user);
                }

                logger.debug("searchByName");
                optionLists.put("landList", landList);


            } else if (type.equals("subDividedLand")) {
                if (mode.equals("byGNDivision")) {
                    if (Integer.parseInt(id) == AppConstants.ALL) {
                        // optionLists.put("landList", landDAO.getAllActivePendingLands(user));
                        //todo: move to service, remove lazy error
                        optionLists.put("landList", landManagementService.getSubDividedLandsTobeApproveByDSDivision(user));
                        logger.debug("Listing all subDivided lands for approval by {}", user.getUsername());
                    } else {
                        optionLists.put("landList", landManagementService.getSubDividedLandsTobeApproveByGNDivision(Integer.parseInt(id), user));
                        //TODO: Wrong log info - it doesn't print Number of lands.
                        logger.debug("Land Lookup by G.N. Division [No of lands: {}]", optionLists.size());
                    }
                }
            } else if (type.equals("subDividedLandEdit")) {
                if (mode.equals("byGNDivision")) {
                    if (Integer.parseInt(id) == AppConstants.ALL) {
                        // optionLists.put("landList", landDAO.getAllActivePendingLands(user));
                        //todo: move to service, remove lazy error
                        optionLists.put("landList", landManagementService.getSubDividedLandsTobeEditByDSDivision(user));
                        logger.debug("Listing all subDivided edit lands for approval by {}", user.getUsername());
                    } else {
                        optionLists.put("landList", landManagementService.getSubDividedLandsTobeEditByGNDivision(Integer.parseInt(id), user));
                        //TODO: Wrong log info - it doesn't print Number of lands.
                        logger.debug("Land Lookup by G.N. Division [No of lands: {}]", optionLists.size());
                    }
                }
            } else if (type.equals("preliminaryCandidatesList")) {
                if (mode.equals("byGNDivision")) {
                    logger.debug("preliminaryCandidatesList by gnId {}", Integer.parseInt(id));
                    EnumSet<WorkflowTask> stateSet = EnumSet.of(WorkflowTask.INTERVIEW_COMPLETED,
                            WorkflowTask.OBJECTION_DATA_ENTRY);
                    List<LandApplication> list = new ArrayList<LandApplication>();
                    if (Integer.parseInt(id) == AppConstants.ALL) {

                        list = landApplicationManagementService.getApplicationsByStateSet(user, stateSet);
                        logger.debug("Listing all preliminaryCandidatesList by {}", list.size());
                        optionLists.put("applicationList", populateDetail(list));
                        logger.debug("Listing all preliminaryCandidatesList by {}", user.getUsername());
                    } else {
                        //list=landApplicationManagementService.getApplicationsByWorkflowState(user, WorkflowTask.OBJECTION_DATA_ENTRY);

                        list = landApplicationManagementService.getApplicationsByStateSetGn(user, Integer.parseInt(id), stateSet);
                        logger.debug("Listing all preliminaryCandidatesList by {}", list.size());
                        optionLists.put("applicationList", populateDetail(list));
                        logger.debug("preliminaryCandidatesList by gn size", optionLists.size());
                    }
                }

            } else if (type.equals("kachchery")) {
                if (mode.equals("toBeApprovedKachcheryList")) {
                    logger.debug("toBeApprovedKachcheryList by ds {}");

                    if (user.getRole().getId().equals(AppConstants.ORDS_USER_ROLE)) {
                        optionLists.put("kachcheryList", populateKachcheryDetail(kachcheryManagementService.getAllKachcheryByDSDivisionAndState(Kachchery.Status.PENDING, user)));

                    } else if (user.getRole().getId().equals(AppConstants.PLC_USER_ROLE)) {
                        optionLists.put("kachcheryList", populateKachcheryDetail(kachcheryManagementService.getAllKachcheryByDSDivisionAndState(Kachchery.Status.ATTACH_DOC_LO, user)));

                    } else if (user.getRole().getId().equals(AppConstants.LO_USER_ROLE)) {
                        optionLists.put("kachcheryList", populateKachcheryDetail(kachcheryManagementService.getAllKachcheryByDSDivisionAndState(Kachchery.Status.PENDING, user)));

                    }


                } else if (mode.equals("toBeApprovedKachcheryLandList")) {
                    logger.debug("toBeApprovedKachcheryLandList by ds {}");
                    optionLists.put("landAssociationDetailsList", kachcheryManagementService.getLandListByKachcheryId(Long.parseLong(id)));

                } else if (mode.equals("kachcheryRejectList")) {
                    logger.debug("kachcheryRejectList by ds {}");

                    if (user.getRole().getId().equals(AppConstants.ORDS_USER_ROLE)) {
                        optionLists.put("kachcheryList", populateKachcheryDetail(kachcheryManagementService.getAllKachcheryByDSDivisionAndState(Kachchery.Status.REJECT_PLC, user)));

                    } else if (user.getRole().getId().equals(AppConstants.LO_USER_ROLE)) {
                        optionLists.put("kachcheryList", populateKachcheryDetail(kachcheryManagementService.getAllKachcheryByDSDivisionAndState(Kachchery.Status.REJECT_ORDS, user)));

                    }


                } else if (mode.equals("toBeAttachDocList")) {
                    logger.debug("kachcheryRejectList by lo {}");

                    if (user.getRole().getId().equals(AppConstants.LO_USER_ROLE)) {
                        optionLists.put("kachcheryList", populateKachcheryDetail(kachcheryManagementService.getAllKachcheryByDSDivisionAndState(Kachchery.Status.APPROVE_ORDS, user)));

                    }

                }

            } else if (type.equals("report")) {
                String pageNo = request.getParameter("pageNo");
                int alienationStateId = Integer.parseInt(request.getParameter("alienation"));
                int alienationMethodId = 0;
                if (alienationStateId == 2)
                    alienationMethodId = Integer.parseInt(request.getParameter("alienationMethod"));
                int geoTypeId = Integer.parseInt(request.getParameter("geoType"));
                Land.AlienationState alienationState = null;
                if (alienationStateId > 0) {
                    alienationState = Land.AlienationState.values()[alienationMethodId - 1];
                }

                optionLists.put("landList", landManagementService.getAllLandsReport(Integer.parseInt(id), getSearchBy(mode, id), alienationState, alienationMethodId, geoTypeId, language, Integer.parseInt(pageNo)));
                logger.debug("Land lookup [Number of lands: {}]", optionLists.size());
            } else if (type.equals("landStat")) {
                Date fromDate;
                Date toDate;
                try {
                    fromDate = new Date(Long.parseLong(request.getParameter("fromDate")));
                    toDate = new Date(Long.parseLong(request.getParameter("toDate")));
                } catch (NumberFormatException e) {
                    fromDate = null;
                    toDate = null;
                }
                int landStateId = Integer.parseInt(request.getParameter("landState"));
                Land.ApprovalState landState = null;
                if (landStateId > 0) {
                    landState = Land.ApprovalState.values()[landStateId - 1];
                }

                int migState = Integer.parseInt(request.getParameter("migState"));

                optionLists.put("landList", landManagementService.getLandStats(Integer.parseInt(id), getSearchBy(mode, id), landState, fromDate, toDate, migState));
                logger.debug("Land Statistic [Number of lands: {}]", optionLists.size());
            } else if (type.equals("landAppStat")) {
                Date fromDate;
                Date toDate;
                try {
                    fromDate = new Date(Long.parseLong(request.getParameter("fromDate")));
                    toDate = new Date(Long.parseLong(request.getParameter("toDate")));
                } catch (NumberFormatException e) {
                    fromDate = null;
                    toDate = null;
                }
                int landAppStateId = Integer.parseInt(request.getParameter("landAppState"));
                int initAppState = 0;
                int wftState = 0;

                if (landAppStateId > 0) {
                    //int len = LandApplication.State.values().length;
                    if (landAppStateId == 1) {
                        //initAppState = LandApplication.State.values()[landAppStateId - 1];
                        initAppState = 1;
                    } else {
                        // wftState = WorkflowTask.values()[landAppStateId - (len + 1)];
                        wftState = landAppStateId;
                    }
                }

                optionLists.put("landList", landApplicationManagementService.getLandApplicationStats(Integer.parseInt(id), getApplicationSearchBy(mode, id), initAppState, wftState, fromDate, toDate, language));


            } else if (type.equals("rail_payment")) {
                if (mode.equals("byLand")) {
                    String l_no = request.getParameter("id");
                    EnumSet<LandRailway.State> stateSet = EnumSet.of(LandRailway.State.APPROVED);

                    //optionLists.put("landRailwayDetailList", populateLandRailwayDetails(landRailwayDAO.getLandByFileNumberByUser(l_no,user),user));
                    optionLists.put("landRailwayDetailList", populateLandRailwayDetails(landRailwayDAO.getLandByFileNumberByUserAndState(l_no, user, stateSet), user));


                } else if (mode.equals("byLease")) {
                    String l_no = request.getParameter("id");
                    //EnumSet<AlienationRailway.State> stateSet = EnumSet.of(AlienationRailway.State.APPROVED_BY_DH);
                    EnumSet<AlienationRailway.State> stateSet = EnumSet.of(AlienationRailway.State.DATA_ENTRY);
                    //optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByAlienation(alienationRailwayDAO.getAlienationRailwayByLeaseId(user, l_no)));
                    optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByAlienation(alienationRailwayDAO.getAlienationRailwayByLeaseIdAndStateSet(user, l_no, stateSet)));

                } else if (mode.equals("paymentToApprove")) {

                    optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByPayment(paymentDAO.getPaymentByUserAndState(Payment.PaymentState.INVOICED, user), user));
                } else if (mode.equals("paymentToEdit")) {

                    optionLists.put("landRailwayDetailList", populateLandRailwayDetailsByPayment(paymentDAO.getAllPaymentByUserAndState(Payment.PaymentState.INVOICED, user), user));
                }
            }
        } catch (Exception e) {
            logger.error("Fatal Error : {}", e);
            return;
        }
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        try {
            mapper.writeValue(out, optionLists);
            out.flush();
        } catch (Exception e) {
            logger.error(e.getMessage());
        }
    }

    private String getApplicationSearchBy(String mode, String id) {
        String searchBy = null;
        if (mode.equals("byProvince")) {
            if (Integer.parseInt(id) == 0) {
                logger.debug("Land lookup by All Province");
            } else {
                searchBy = " l.dsDivision.district.province.id = :divisionId";
                logger.debug("Land lookup by Province");
            }
        } else if (mode.equals("byDistrict")) {
            searchBy = " l.dsDivision.district.id = :divisionId";
            logger.debug("Land lookup by District");
        } else if (mode.equals("byDSDivision")) {
            searchBy = " l.dsDivision.id = :divisionId";
            logger.debug("Land lookup by D.S. Division");
        }
        return searchBy;
    }

    private List<LandApplicationDetail> populateDetail(List<LandApplication> landApplications) {
        List<LandApplicationDetail> list = new ArrayList<LandApplicationDetail>();
        for (LandApplication landApplication : landApplications) {
            LandApplicationDetail landApplicationDetail = new LandApplicationDetail();
            landApplicationDetail.setSubmitDate(landApplication.getSubmitDate());
            landApplicationDetail.setHolderName(landApplication.getHolder().getName());
            landApplicationDetail.setHolderAddress(landApplication.getHolder().getContacts().getAddress());
            list.add(landApplicationDetail);
        }
        return list;
    }

    private List<KachcheryDetails> populateKachcheryDetail(List<Kachchery> kachcheryList) {
        List<KachcheryDetails> list = new ArrayList<KachcheryDetails>();
        for (Kachchery kachchery : kachcheryList) {
            KachcheryDetails kachcheryDetails = new KachcheryDetails();

            kachcheryDetails.setId(kachchery.getId());
            kachcheryDetails.setName(kachchery.getName());

            list.add(kachcheryDetails);
        }
        return list;
    }

    private List<LandRailwayDetails> populateLandRailwayDetails(List<LandRailway> landRailwayList, User user) {
        List<LandRailwayDetails> list = new ArrayList<LandRailwayDetails>();
        for (LandRailway landRailway : landRailwayList) {
            LandRailwayDetails railwayDetails = new LandRailwayDetails();

            railwayDetails.setId(landRailway.getId());
            railwayDetails.setLandFileNumber(landRailway.getLandFileNumber());
            railwayDetails.setPlanNumber(landRailway.getPlanNumber());
            railwayDetails.setLotNumber(landRailway.getLotNumber());
            railwayDetails.setLandExtent(landRailway.getLandExtent());
            railwayDetails.setDistrictName(landRailway.getDistrict().getEnDistrictName());
            railwayDetails.setAlienationId(alienationRailwayDAO.getActiveAlienationByLandId(landRailway.getId(), user).getId());
            railwayDetails.setLeaseNumber(alienationRailwayDAO.getActiveAlienationByLandId(landRailway.getId(), user).getReferenceNo());
            list.add(railwayDetails);

        }

        return list;

    }

    private List<LandRailwayDetails> populateLandRailwayDetailsByAlienation(List<AlienationRailway> alienationRailways) {
        List<LandRailwayDetails> list = new ArrayList<LandRailwayDetails>();
        for (AlienationRailway alienationRailway : alienationRailways) {
            LandRailwayDetails railwayDetails = new LandRailwayDetails();

            railwayDetails.setId(alienationRailway.getLand().getId());
            railwayDetails.setLandFileNumber(alienationRailway.getLand().getLandFileNumber());
            railwayDetails.setPlanNumber(alienationRailway.getLand().getPlanNumber());
            railwayDetails.setLotNumber(alienationRailway.getLand().getLotNumber());
            railwayDetails.setLandExtent(alienationRailway.getLand().getLandExtent());
            railwayDetails.setDistrictName(alienationRailway.getLand().getDistrict().getEnDistrictName());
            railwayDetails.setAlienationId(alienationRailway.getId());
            railwayDetails.setLeaseNumber(alienationRailway.getReferenceNo());

            list.add(railwayDetails);

        }

        return list;

    }

    private List<LandRailwayDetails> populateLandRailwayDetailsByPayment(List<Payment> paymentList, User user) {


        List<LandRailwayDetails> list = new ArrayList<LandRailwayDetails>();
        for (Payment payment : paymentList) {

            AlienationRailway alienationRailway = alienationRailwayDAO.getAlienationById(payment.getAlienationId(), user);
            if (alienationRailway != null) {
                LandRailwayDetails railwayDetails = new LandRailwayDetails();

                railwayDetails.setId(payment.getId());
                railwayDetails.setLandFileNumber(alienationRailway.getLand().getLandFileNumber());
                railwayDetails.setPlanNumber(alienationRailway.getLand().getPlanNumber());
                railwayDetails.setLotNumber(alienationRailway.getLand().getLotNumber());
                railwayDetails.setLandExtent(alienationRailway.getLand().getLandExtent());
                railwayDetails.setDistrictName(alienationRailway.getLand().getDistrict().getEnDistrictName());
                railwayDetails.setAlienationId(alienationRailway.getId());
                railwayDetails.setReceiptReferenceNo(payment.getReceiptReferenceNo());
                railwayDetails.setLeaseNumber(alienationRailway.getReferenceNo());

                list.add(railwayDetails);

            }

        }

        return list;

    }

    private String getSearchBy(String mode, String id) {
        String searchBy = null;
        if (mode.equals("byProvince")) {
            if (Integer.parseInt(id) == 0) {
                logger.debug("Land lookup by All Province");
            } else {
                searchBy = " l.gnDivision.dsDivision.district.province.id = :divisionId";
                logger.debug("Land lookup by Province");
            }
        } else if (mode.equals("byDistrict")) {
            searchBy = " l.gnDivision.dsDivision.district.id = :divisionId";
            logger.debug("Land lookup by District");
        } else if (mode.equals("byDSDivision")) {
            searchBy = " l.gnDivision.dsDivision.id = :divisionId";
            logger.debug("Land lookup by D.S. Division");
        } else if (mode.equals("byGNDivision")) {
            searchBy = " l.gnDivision.id = :divisionId";
            logger.debug("Land lookup by G.N. Division");
        }
        return searchBy;
    }


}
